﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Entity.IRepository.Project;
using Entity.ProjectEnt;
using Logic.Repository.Project;
using ZFine.Code;

namespace ZFine.Application.Project
{
    public class OperationGudaoCarApp
    {

        private IOperationGudaoCarRepository service = new OperationGudaoCarRepository();
        private  IPathwayRepository pathwayservice=new PathwayRepository();
        private  IGudaoCarRepository gudaocarservice=new GudaoCarRepository();
        private  IHistoryGudaoCarRepository historygudaoservice=new HistoryGudaoCarRepository();

        public List<OperationGudaoCarEntity> GetList()
        {
            return service.IQueryable().ToList();
        }
        public List<OperationGudaoCarEntity> GetList(Expression<Func<OperationGudaoCarEntity, bool>> predicate)
        {
            return service.IQueryable(predicate).ToList();
        }
        public List<OperationGudaoCarEntity> GetListD(Pagination pagination, Expression<Func<OperationGudaoCarEntity, bool>> predicate)
        {
            var expression = ExtLinq.True<OperationGudaoCarEntity>();
            expression = expression.And(t => t.State == true);
            expression = expression.And(predicate);
            return service.FindList(expression, pagination);
        }

        public List<OperationGudaoCarEntity> GetList(Pagination pagination, string keyword)
        {
            var expression = ExtLinq.True<OperationGudaoCarEntity>();
            expression = expression.And(t => t.State == true);
            return service.FindList(expression, pagination);
        }


        public List<OperationGudaoCarEntity> GetListD(Pagination pagination, string keyword)
        {
            var expression = ExtLinq.True<OperationGudaoCarEntity>();
            expression = expression.And(t => t.State == true);
            return service.FindList(expression, pagination);
        }

        /// <summary>
        /// 执行计划
        /// </summary>
        /// <param name="thisoperationgudao"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public int SubmitExecutePlan(OperationGudaoCarEntity thisoperationgudao, ref string msg)
        {
            int code = 0;
            if (!string.IsNullOrEmpty(thisoperationgudao.WorkPlan.BianZhiPlan))
            {
                List<ClientPlay> objlist = Json.ToList<ClientPlay>(thisoperationgudao.WorkPlan.BianZhiPlan);
                List<PathwayEntity> AllPathwaylist = new List<PathwayEntity>();
                var gudaoinfo = new WorkPlanApp().getgudaoAllinfo(ref AllPathwaylist);
                Dictionary<string, List<GudaoCarEntity>> thisgudaolsit = new Dictionary<string, List<GudaoCarEntity>>();
                foreach (var item in gudaoinfo)
                {
                    if (item.ToList()[0].BelongCarriage != null)
                    {

                        thisgudaolsit.Add(item.Key.Name, item.OrderBy(f => f.CarGudaoIndex).ToList());
                    }
                    else
                    {
                        thisgudaolsit.Add(item.Key.Name, new List<GudaoCarEntity>());
                    }
                }
                foreach (var item in AllPathwaylist)//将空股道信息也添加进来
                {
                    if (thisgudaolsit.Keys.ToList().Find(f => f.Equals(item.Name)) == null)
                    {
                        thisgudaolsit.Add(item.Name, new List<GudaoCarEntity>());
                    }
                }
                //排出的车辆信息(堆栈stack:先进后出)
                Stack<GudaoCarEntity> xinullgudaocarlist = new Stack<GudaoCarEntity>();
                Stack<GudaoCarEntity> dongnullgudaocarlist = new Stack<GudaoCarEntity>();
                for (int i = 0; i < objlist.Count; i++)
                {
                    //+是从股道里往出拉车 -是往股道里加车
                    if (objlist[i].fangfa == "+" && objlist[i].fangxiang == "西")
                    {
                        code = xiRemoveGudao(xinullgudaocarlist, thisgudaolsit, objlist[i], ref msg);
                        if (code < 0)
                        {
                            return code;
                        }
                    }
                    else if (objlist[i].fangfa == "+" && objlist[i].fangxiang == "东")
                    {
                        code = dongRemoveGudao(dongnullgudaocarlist, thisgudaolsit, objlist[i], ref msg);
                        if (code < 0)
                        {
                            return code;
                        }
                    }
                    else if (objlist[i].fangfa == "-" && objlist[i].fangxiang == "西")
                    {
                        code = AddxiToGudao(xinullgudaocarlist, thisgudaolsit, objlist[i], ref msg);
                        if (code < 0)
                        {
                            return code;
                        }
                    }
                    else if (objlist[i].fangfa == "-" && objlist[i].fangxiang == "东")
                    {
                        code = AddDongToGudao(dongnullgudaocarlist, thisgudaolsit, objlist[i], ref msg);
                        if (code < 0)
                        {
                            return code;
                        }
                    }
                }

                //清除历史数据
                var result = gudaocarservice.GetIncludeList(f => f.State == true); //获取当前有效的所有股道上的车
                List<OperationGudaoCarEntity> OperationAlllist = (from Var in result select Var.Operation).Distinct().ToList();
                OperationAlllist.RemoveAll(f => f == null);
                List<OperationGudaoCarEntity> PassOperAlllsit = (from Var in result select Var.PassOper).Distinct().ToList();
                PassOperAlllsit.RemoveAll(f => f == null);
                List<OperationGudaoCarEntity> QiPiaoOperAlllist = (from Var in result select Var.QiPiaoOper).Distinct().ToList();
                QiPiaoOperAlllist.RemoveAll(f => f == null);
                List<OperationGudaoCarEntity> ClearGudaoOperAlllist = (from Var in result select Var.ClearGudaoOper).Distinct().ToList();
                ClearGudaoOperAlllist.RemoveAll(f => f == null);

                List<PathwayEntity> hisusepathlist = (from var in result select var.BelongPathway).Distinct().ToList();
                for (int i = 0; i < hisusepathlist.Count; i++)//同步ef
                {
                    for (int j = 0; j < AllPathwaylist.Count; j++)
                    {
                        if (AllPathwaylist[j].F_Id == hisusepathlist[i].F_Id)
                        {
                            AllPathwaylist[j] = hisusepathlist[i];
                        }
                    }
                }
                //从新设置股道
                List<GudaoCarEntity> newgudaolist=new List<GudaoCarEntity>();
                foreach (var gudaolist in thisgudaolsit)
                {
                    //var gudaoent = pathwayservice.FindEntity(f => f.Name == gudaolist.Key && f.State == true);
                    //if (gudaoent != null)
                    //{
                      
                        foreach (var gudaocarlist in gudaolist.Value)
                        {
                            gudaocarlist.Create();
                            gudaocarlist.WorkPlanOper = thisoperationgudao;
                            gudaocarlist.BelongPathway = AllPathwaylist.Find(f => f.Name == gudaolist.Key);
                            //result.Find(f=>f.BelongPathway.Name== gudaolist.Key).BelongPathway;
                            gudaocarlist.BelongCarriage= result.Find(f => f.BelongCarriage.F_Id == gudaocarlist.BelongCarriage.F_Id).BelongCarriage;
                            if (gudaocarlist.Operation != null)
                            {
                                gudaocarlist.Operation = OperationAlllist.Find(f => f.F_Id == gudaocarlist.Operation.F_Id);
                            }
                            if (gudaocarlist.PassOper != null)
                            {
                                gudaocarlist.PassOper = PassOperAlllsit.Find(f => f.F_Id == gudaocarlist.PassOper.F_Id);
                            }
                            if (gudaocarlist.QiPiaoOper != null)
                            {
                                gudaocarlist.QiPiaoOper = QiPiaoOperAlllist.Find(f => f.F_Id == gudaocarlist.QiPiaoOper.F_Id);
                            }
                            if (gudaocarlist.ClearGudaoOper != null)
                            {
                                gudaocarlist.ClearGudaoOper = ClearGudaoOperAlllist.Find(f => f.F_Id == gudaocarlist.ClearGudaoOper.F_Id);
                            }
                            if (gudaocarlist.DuiWeiOper != null)
                            {
                                gudaocarlist.DuiWeiOper = ClearGudaoOperAlllist.Find(f => f.F_Id == gudaocarlist.DuiWeiOper.F_Id);
                            }
                            if (gudaocarlist.RecoveryOper != null)
                            {
                                gudaocarlist.RecoveryOper = ClearGudaoOperAlllist.Find(f => f.F_Id == gudaocarlist.RecoveryOper.F_Id);
                            }  
                            newgudaolist.Add(gudaocarlist);
                        }
                    //}
                    //else
                    //{
                    //    msg = string.Format("股道:{0} 不存在，执行计划失败", gudaolist.Key);
                    //    return -1;
                    //}
                }
             
                List<HistoryGudaoCarEntity> historygudaocarlist = new List<HistoryGudaoCarEntity>();//计划保存历史数据
                foreach (var item in result)
                {
                    HistoryGudaoCarEntity temp = new HistoryGudaoCarEntity();
                    temp.Create();
                    temp.ThingsName = item.ThingsName;
                    temp.Fenhao = item.Fenhao;
                    temp.isQiPiao = item.isQiPiao;
                    temp.QiPiaoTime = item.QiPiaoTime;
                    temp.ArriveDateTime = item.ArriveDateTime;
                    temp.CarGudaoIndex = item.CarGudaoIndex;
                    temp.isAccomplishStatistics = item.isAccomplishStatistics;
                    temp.AccomplishStatisticsTime = item.AccomplishStatisticsTime;
                    temp.IsAccomplishPermitThrough = item.IsAccomplishPermitThrough;
                    temp.AccomplishPermitThroughTime = item.AccomplishPermitThroughTime;
                    temp.isAccomplishPaiche = item.isAccomplishPaiche;
                    temp.AccomplishPaicheTime = item.AccomplishPaicheTime;
                    temp.IsAccomplishduiwei = item.IsAccomplishduiwei;
                    temp.AccomplishduiweiTime = item.AccomplishduiweiTime;
                    temp.Remark = item.Remark;
                    temp.ArriveStation = item.ArriveStation;
                    temp.Weight = item.Weight;
                    temp.UnitNumber = item.UnitNumber;
                    temp.Customers = item.Customers;
                    temp.State = item.State;
                    temp.BelongPathway = item.BelongPathway;
                    temp.BelongCarriage = item.BelongCarriage;
                    temp.Operation = item.Operation;
                    temp.PassOper = item.PassOper;
                    temp.QiPiaoOper = item.QiPiaoOper;
                    temp.ClearGudaoOper = item.ClearGudaoOper;
                    temp.WorkPlanOper = item.WorkPlanOper;
                    temp.DuiWeiOper = item.DuiWeiOper;
                    temp.RecoveryOper = item.RecoveryOper;
                    historygudaocarlist.Add(temp);
                }
                //插入数据库
                thisoperationgudao.IsExecute = true;
                thisoperationgudao.ExecuteDateTime=DateTime.Now;
                code = service.SubmitAllPlan(historygudaocarlist, result, newgudaolist, thisoperationgudao);
                if (code >= 0)
                {
                    msg = "计划执行成功";
                }
                else
                {
                    msg = "计划执行失败，请稍后重试";
                }
            }
            else
            {
                code = -1;
                msg = "此计划无详细说明";
            }
            return code;
        }

        public int SubmitExecuteReturnPlan(OperationGudaoCarEntity thisoperationgudao, ref string msg)
        {
            int code = 0;
            List<HistoryGudaoCarEntity> historylist =
                historygudaoservice.FindList(f => f.WorkPlanOper.F_Id == thisoperationgudao.F_Id&&f.State==true&&f.CarGudaoIndex!=null);//f.CarGudaoIndex!=null 特殊处理 将排车完成的数据排除出去，避免数据冗余
            if (historylist!=null&& historylist.Count>0)
            {
                List<GudaoCarEntity> retrunGudaocarlist=new List<GudaoCarEntity>();
                foreach (var item in historylist)
                {
                    GudaoCarEntity temp = new GudaoCarEntity();
                    temp.Create();
                    temp.ThingsName = item.ThingsName;
                    temp.Fenhao = item.Fenhao;
                    temp.isQiPiao = item.isQiPiao;
                    temp.QiPiaoTime = item.QiPiaoTime;
                    temp.CarGudaoIndex = item.CarGudaoIndex;
                    temp.ArriveDateTime = item.ArriveDateTime;
                    temp.isAccomplishStatistics = item.isAccomplishStatistics;
                    temp.AccomplishStatisticsTime = item.AccomplishStatisticsTime;
                    temp.IsAccomplishPermitThrough = item.IsAccomplishPermitThrough;
                    temp.AccomplishPermitThroughTime = item.AccomplishPermitThroughTime;
                    temp.isAccomplishPaiche = item.isAccomplishPaiche;
                    temp.AccomplishPaicheTime = item.AccomplishPaicheTime;
                    temp.IsAccomplishduiwei = item.IsAccomplishduiwei;
                    temp.AccomplishduiweiTime = item.AccomplishduiweiTime;
                    temp.Remark = item.Remark;
                    temp.ArriveStation = item.ArriveStation;
                    temp.Weight = item.Weight;
                    temp.UnitNumber = item.UnitNumber;
                    temp.Customers = item.Customers;
                    temp.State = item.State;
                    temp.BelongPathway = item.BelongPathway;
                    temp.BelongCarriage = item.BelongCarriage;
                    temp.Operation = item.Operation;
                    temp.PassOper = item.PassOper;
                    temp.QiPiaoOper = item.QiPiaoOper;
                    temp.ClearGudaoOper = item.ClearGudaoOper;
                    temp.WorkPlanOper = item.WorkPlanOper;
                    temp.DuiWeiOper = item.DuiWeiOper;
                    temp.RecoveryOper = item.RecoveryOper;
                    retrunGudaocarlist.Add(temp);
                }

                thisoperationgudao.IsRollBack = true;
                thisoperationgudao.RollbackTime=DateTime.Now;
                List<GudaoCarEntity> deletegudaolist = gudaocarservice.FindEntityAsNoTrackinglist(f => f.State == true);
                code = service.SubmitAllReturnPlan(retrunGudaocarlist, deletegudaolist, thisoperationgudao);
                if (code >= 0)
                {
                    msg = "计划回退成功";
                }
                else
                {
                    msg = "计划回退失败，请稍后重试";
                }
            }
            return code;
        }

        /// <summary>
        /// 西往股道里加车
        /// </summary>
        /// <param name="xinullgudaocarlist"></param>
        /// <param name="thisgudaolsit"></param>
        /// <param name="clientPlay"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        private int AddxiToGudao(Stack<GudaoCarEntity> xinullgudaocarlist, Dictionary<string, List<GudaoCarEntity>> thisgudaolsit, ClientPlay clientPlay, ref string msg)
        {
            int code = 0;
            int chucount = clientPlay.cheshu;
            if (chucount > xinullgudaocarlist.Count)
            {
                msg = string.Format("计划创建时有错误，操作股道{0}，方法{1}，数量{2}，方向：{3},错误信息：往股道里加车不足，非股道中的车数：{4}", clientPlay.gudao,
                    clientPlay.fangfa, clientPlay.cheshu, clientPlay.fangxiang, xinullgudaocarlist.Count);
                code = -2;
            }
            else
            {
                //int popcount = xinullgudaocarlist.Count;
                //向指定股道中添加车辆
                for (int i = 0; i < chucount; i++)
                {
                    var sortindex = 0; 
                    if (thisgudaolsit[clientPlay.gudao].Count == 0)
                    {
                        sortindex= thisgudaolsit[clientPlay.gudao].Count + i + 1;
                    }
                    else
                    {
                        sortindex = thisgudaolsit[clientPlay.gudao].Count + 1;
                    }
                    var temp = xinullgudaocarlist.Peek();
                    temp.CarGudaoIndex = sortindex;
                    xinullgudaocarlist.Pop();
                    thisgudaolsit[clientPlay.gudao].Add(temp);
                    //thisgudaolsit[clientPlay.gudao].Insert(0,temp);
                }
                //从新排序
                //for (int i = 0; i < thisgudaolsit[clientPlay.gudao].Count; i++)
                //{
                //    thisgudaolsit[clientPlay.gudao][i].CarGudaoIndex = 1 + i;
                //}
            }
            return code;
        }

        /// <summary>
        /// 东 往股道里加车
        /// </summary>
        /// <param name="xinullgudaocarlist"></param>
        /// <param name="thisgudaolsit"></param>
        /// <param name="clientPlay"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        private int AddDongToGudao(Stack<GudaoCarEntity> xinullgudaocarlist, Dictionary<string, List<GudaoCarEntity>> thisgudaolsit, ClientPlay clientPlay, ref string msg)
        {
            int code = 0;
            int chucount = clientPlay.cheshu;
            if (chucount > xinullgudaocarlist.Count)
            {
                msg = string.Format("计划创建时有错误，操作股道{0}，方法{1}，数量{2}，方向：{3},错误信息：往股道里加车不足，非股道中的车数：{4}", clientPlay.gudao,
                    clientPlay.fangfa, clientPlay.cheshu, clientPlay.fangxiang, xinullgudaocarlist.Count);
                code = -2;
            }
            else
            {
                //int popcount = xinullgudaocarlist.Count;
                for (int i = 0; i < chucount; i++)
                {
                    //int index = thisgudaolsit[clientPlay.gudao].Count + i + 1;//入车的序号
                    var temp = xinullgudaocarlist.Peek();
                    xinullgudaocarlist.Pop();
                    //temp.CarGudaoIndex = index;
                    thisgudaolsit[clientPlay.gudao].Insert(0,temp);
                }
                //从新排序
                for (int i = 0; i < thisgudaolsit[clientPlay.gudao].Count; i++)
                {
                    thisgudaolsit[clientPlay.gudao][i].CarGudaoIndex = 1 + i;
                }

            }
            return code;
        }

        /// <summary>
        /// 从股道里往出拉车 东方向
        /// </summary>
        /// <param name="xinullgudaocarlist">转变股道 西/东</param>
        /// <param name="thisgudaolsit">所有股道中信息</param>
        /// <param name="msg">返回消息</param>
        /// <returns></returns>
        private int dongRemoveGudao(Stack<GudaoCarEntity> xinullgudaocarlist,
            Dictionary<string, List<GudaoCarEntity>> thisgudaolsit, ClientPlay clientPlay, ref string msg)
        {
            int code = 0;
            int chucount = clientPlay.cheshu;
            if (chucount > thisgudaolsit[clientPlay.gudao].Count)
            {
                msg = string.Format("计划创建时有错误，操作股道{0}，方法{1}，数量{2}，方向：{3},错误信息：从股道里往出拉车不足，股道中实有车数{4}", clientPlay.gudao,
                    clientPlay.fangfa, clientPlay.cheshu, clientPlay.fangxiang, thisgudaolsit[clientPlay.gudao].Count);
                code = -2;
            }
            else
            {
                //东外测加车
                for (int i = 0; i < chucount; i++)
                {
                    xinullgudaocarlist.Push(thisgudaolsit[clientPlay.gudao][i]);
                }
                thisgudaolsit[clientPlay.gudao].RemoveRange(0, chucount);//将排出去的车删除
                //从东出去需要排序
                for (int i = 0; i < thisgudaolsit[clientPlay.gudao].Count; i++)
                {
                    thisgudaolsit[clientPlay.gudao][i].CarGudaoIndex =
                        thisgudaolsit[clientPlay.gudao][i].CarGudaoIndex - chucount;
                }

            }
            return code;
        }

        /// <summary>
        /// 从股道里往出拉车 西方向
        /// </summary>
        /// <param name="xinullgudaocarlist">转变股道 西/东</param>
        /// <param name="thisgudaolsit">所有股道中信息</param>
        /// <param name="msg">返回消息</param>
        /// <returns></returns>
        private int xiRemoveGudao(Stack<GudaoCarEntity> xinullgudaocarlist, Dictionary<string, List<GudaoCarEntity>> thisgudaolsit, ClientPlay clientPlay, ref string msg)
        {
            int code = 0;
            int chucount = clientPlay.cheshu;
            if (chucount > thisgudaolsit[clientPlay.gudao].Count)
            {
                msg = string.Format("计划创建时有错误，操作股道{0}，方法{1}，数量{2}，方向：{3},错误信息：从股道里往出拉车不足，股道中实有车数{4}", clientPlay.gudao,
                    clientPlay.fangfa, clientPlay.cheshu, clientPlay.fangxiang, thisgudaolsit[clientPlay.gudao].Count);
                code = -2;
            }
            else
            {
                var lastindex = thisgudaolsit[clientPlay.gudao].Count  - chucount;
                //西外测加车
                for (int i = thisgudaolsit[clientPlay.gudao].Count-1; i >= lastindex; i--)
                {
                    xinullgudaocarlist.Push(thisgudaolsit[clientPlay.gudao][i]);
                }
                //将排出去的车删除
                thisgudaolsit[clientPlay.gudao].RemoveRange(lastindex, chucount);

                ////西外测加车
                //for (int i = 0; i < chucount; i++)
                //{
                //    xinullgudaocarlist.Push(thisgudaolsit[clientPlay.gudao][i]);
                //}
                //thisgudaolsit[clientPlay.gudao].RemoveRange(0, chucount);//将排出去的车删除
                ////从新计算排序
                //for (int i = 0; i < thisgudaolsit[clientPlay.gudao].Count; i++)
                //{
                //    thisgudaolsit[clientPlay.gudao][i].CarGudaoIndex =
                //        thisgudaolsit[clientPlay.gudao][i].CarGudaoIndex - chucount;
                //}
            }
            return code;
        }

        public OperationGudaoCarEntity GetForm(string keyValue)
        {
            return service.FindEntity(keyValue);
        }
        public int modifDeletePlan(string keyValue)
        {
            var local = service.FindEntity(keyValue);
            if (local != null)
            {
                local.State = false;
                return service.Update(local);
            }
            else
            {
                return -1;
            }
        }
        public int SubmitForm(OperationGudaoCarEntity ServiceEntity, string keyValue)
        {
            var LoginInfo = OperatorProvider.Provider.GetCurrent();
            if (LoginInfo != null)
            {
                if (!string.IsNullOrEmpty(keyValue))
                {
                    ServiceEntity.Modify(keyValue);
                    return service.Update(ServiceEntity);
                }
                else
                {
                    ServiceEntity.Create();
                    ServiceEntity.State = true;
                    return service.Insert(ServiceEntity);
                }
            }
            return -1;
        }

        public OperationGudaoCarEntity GetEntityInclued(Expression<Func<OperationGudaoCarEntity, bool>> predicate)
        {
            return service.FindEntity(predicate);
        }
        public OperationGudaoCarEntity GetEntityIncluedTwo(Expression<Func<OperationGudaoCarEntity, bool>> predicate)
        {
            return service.FindincludeTwo(predicate);
        }

        public OperationGudaoCarEntity GetOnTrackEnt(Expression<Func<OperationGudaoCarEntity, bool>> predicate)
        {
            return service.FindEntityAsNoTracking(predicate);
        }
    }
}
